﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;

namespace ITSP_Instance_Generator
{
    class Experiment
    {
        public List<IGenerator> Generator { get; private set; }
        public int NumberOfRuns { get; private set; }
        public String Output;
        private readonly Stopwatch _stopwatch;
        private Process process; 
        public Experiment(List<IGenerator> generatorList, int numberOfRuns)
        {
            Generator = generatorList;
            NumberOfRuns = numberOfRuns;
            Output = "";
            _stopwatch = new Stopwatch();
        }
        public Experiment(IGenerator generator, int numberOfRuns)
            : this(new List<IGenerator> { generator }, numberOfRuns)
        {
        }

        private Instance currentInstance;
        private IGenerator currentGenerator;
        public String Run()
        {
            foreach (IGenerator g in Generator)
            {
                currentGenerator = g;
                for (int runNr = 0; runNr < NumberOfRuns;)
                {
                    currentInstance = g.Generate();
                    File.WriteAllText("input.zpl", currentInstance.ToZIMPL()); // overwrite input file
                    var info = new ProcessStartInfo("scip-3.1.0.win.x86_64.msvc.opt.spx.mt.exe", "")
                    {
                        RedirectStandardOutput = true,
                        RedirectStandardInput = true,
                        UseShellExecute = false,
                        CreateNoWindow = true,
                    };
                    process = new Process{StartInfo = info, EnableRaisingEvents = true};
                    process.Start();
                    process.BeginOutputReadLine();
                    StreamWriter writer = process.StandardInput;
                    process.OutputDataReceived += OnOutputDataReceived;

                    //writer.WriteLine("set timing clocktype 2"); // use pc clock as timer, now irrelevant
                    writer.WriteLine("set limits memory 2500");
                    writer.WriteLine("set limits time 900");
                    writer.WriteLine("read input.zpl"); // read thefileName.zpl

                    _stopwatch.Reset();
                    _stopwatch.Start();

                    writer.WriteLine("optimize");
                    writer.WriteLine("display solution");

                    writer.WriteLine("quit");
                    writer.Flush();
                    process.WaitForExit();
                    if (_stopwatch.IsRunning) //scip crashed and couldnt solve the problem
                    {
                        //MessageBox.Show("crash");
                    }
                    else //scip found a solution
                    {
                        Directory.CreateDirectory("experiments\\runs\\" + g.GetTotalNrNodes()); // if the directory doesnt exist, create the directory
                        String outputFileName = "experiments\\runs\\" + g.GetTotalNrNodes() + "\\" + g + ".txt";
                        if (!File.Exists(outputFileName))
                            File.Create(outputFileName).Dispose();
                        using (StreamWriter w = File.AppendText(outputFileName))
                        {
                            w.WriteLine(_stopwatch.ElapsedMilliseconds.ToString());
                            w.Close();
                        }
                        runNr++;
                    }
                }
            }
            return Output;
        }

        public void Close()
        {
            if(process != null)
                process.Close(); // :))
            process = null;
        }
        public void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
        {

            if (_stopwatch.ElapsedMilliseconds > 15*60*1000)
                Close();
            if (e != null && e.Data != null)
            {
                if (e.Data.Contains("optimal solution found"))
                {
                    _stopwatch.Stop();
                    if (_stopwatch.ElapsedMilliseconds > 10000)
                    {
                        File.WriteAllText("largeruntime/" + _stopwatch.ElapsedMilliseconds + "_" + currentGenerator.ToString() + ".txt", currentInstance.ToZIMPL());
                    }
                }
                Output += e.Data + Environment.NewLine;
            }
        }
    }
}
